<template>
    <div class="cascader" ref="cascader" v-click-outside="close">
        <div class="trigger" @click="toggle">
            {{this.result||'&nbsp;'}}
        </div>
        <div class="popover-wrapper" v-if="popoverVisible">
            <cascader-items
                :items="source"
                class="popover"
                :height="popoverHeight"
                :selected="selected"
                @update:selected="onUpdateSelected"
                :loadData="loadData"
                :loadingItem="loadingItem"
            ></cascader-items>
        </div>
    </div>
</template>

<script>
  import CascaderItems from './cascader-items';
  import ClickOutside from './click-outside';

  export default {
    name: "cascader"
    , components: {
      CascaderItems
    }
    ,directives:{ClickOutside}
    , props: {
      source: {
        type: Array
      }
      , popoverHeight: {
        type: String
      }
      , selected: {
        type: Array
        , default: () => {
          return [];
        }
      }
      , loadData: {
        type: Function
      }
    }
    , data() {
      return {
        popoverVisible: true
        ,loadingItem:{}
      }
    }
    , computed: {
      result() {
        return this.selected.map(item => item.name).join('/')
      }
    }
    , methods: {
      /*onUpdateSelected(newSelected){
        //这里的newSelected 是 cascader-items里 onClickLabel(item) 的item
        this.$emit('update:selected', newSelected);
      }*/
      onUpdateSelected(newSelected) {
        this.$emit('update:selected', newSelected);

        let lastItem = newSelected[newSelected.length - 1]; //注意这里的lastItem不是原来传递过来的数据里的，而是深拷贝里的

        let simplest = (children, id) => {
          return children.filter(item => item.id === id)[0];
        };
        let complex = (children, id) => {
          let noChildren = [];
          let hasChildren = [];
          children.forEach(item => {
            if (item.children) {
              hasChildren.push(item);
            } else {
              noChildren.push(item);
            }
          });
          let found = simplest(noChildren, id);
          if (found) {
            return found;
          } else {
            found = simplest(hasChildren, id);
            if (found) {
              return found
            } else {
              for(let i=0;i<hasChildren.length;++i){
                let found = complex(hasChildren[i].children, id);
                if(found) return found;
              }
            }
            return undefined;
          }
        };

        let updateSource = (result) => {
          // let toUpdate = this.source.filter(item => item.id === lastItem.id)[0]; //此时这样在2级中筛选3级就找不到，因为1找2的时候，是将请求回来的2的数据放到1的某项的children里的，而不是直接放到1里

          /*let toUpdate = complex(this.source, lastItem.id);
          this.$set(toUpdate, 'children', result);*/

          //↑直接修改了父数据
          this.loadingItem = {};

          let copy = JSON.parse(JSON.stringify(this.source));
          let toUpdate = complex(copy, lastItem.id);
          toUpdate.children = result;
          this.$emit('update:source', copy);
        };

        if (!lastItem.isLeaf && this.loadData) {
          this.loadData(lastItem, updateSource);
          this.loadingItem = lastItem
        }
      }
      /*,onClickDocument(e){
        let {cascader} = this.$refs;
        let {target} = e;
        if(cascader === target||cascader.contains(target)) {return}
        this.close();
      }*/
      ,close(){
        this.popoverVisible = false;
        // document.removeEventListener('click',this.onClickDocument)
      }
      ,open(){
        this.popoverVisible = true;
        /*this.$nextTick(() => {
          document.addEventListener('click', this.onClickDocument)
        });*/
      }
      ,toggle(){
        if(this.popoverVisible === true){
          this.close();
        }else{
          this.open();
        }
      }
    }
  }
</script>

<style lang="scss">
    @import "var";
    .cascader {
        display:inline-block;
        position: relative;

        .trigger {
            height: $input-height;
            display: inline-flex;
            align-items: center;
            padding: 0 1em;
            min-width: 10em;
            border: 1px solid $border-color;
            border-radius: $border-radius;
        }

        .popover-wrapper {
            position: absolute;
            top: 100%;
            left: 0;
            background: #fff;
            margin-top: 4px;
            z-index:1;
            @extend .box-shadow
        }
    }
</style>
